/**
 * 
 *    Code contributed by IUP Research Institute
 *     This file is part of NetworkMon.
 *
 *   NetworkMon is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; version 2 of the License.
 *
 *   NetworkMon is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with NetworkMon; if not, write to the Free Software
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package networkbackend;

import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * 
 * @author fkern
 */
public class AddressNode {

	public String address;
	public int port;

	// the DNS name of the address for this node
	public String reverseAddress;

	// add the counters here for the total bytes, total packets, etc.
	// TotalNumberOfBytes is currently how many in the Packetlist.
	public long totalSentNumberOfBytes;
	public long totalReceivedNumberOfBytes;

	// Add a totalLifetimePackets for a count of all packets through the
	// lifetime of running.
	public long totalSentLifetimePackets;
	public long totalReceivedLifetimePackets;

	// Add a totalLifeTimeBytes for a count of all Bytes for the Lifetime of
	// running.
	public long totalSentLifetimeBytes;
	public long totalReceivedLifetimeBytes;

	public LinkedList<PacketNode> packetList;

	/** Creates a new instance of AddressNode */
	public AddressNode(String newAddress, int newPort) {
		address = newAddress;
		port = newPort;

		packetList = new LinkedList<PacketNode>();
	}

	public AddressNode() {

	}

	@SuppressWarnings( { "unchecked", "unchecked", "unchecked" })
	public synchronized AddressLinkedList GetListPackets() {
		AddressLinkedList retval = new AddressLinkedList();

		Collections.sort(packetList);

		Iterator iterator = packetList.iterator();

		AddressNode myAddress = null;
		PacketNode myPacket = null;

		while (iterator.hasNext()) {
			myPacket = (PacketNode) iterator.next();

			if (myAddress == null) {
				myAddress = new AddressNode(myPacket.sendersName,
						myPacket.sourcePort);
				myAddress.Save(myPacket);

				retval.add(myAddress);

			} else if (myAddress.address == myPacket.sendersName) {
				myAddress.Save(myPacket);
			} else {
				myAddress = new AddressNode(myPacket.sendersName,
						myPacket.sourcePort);
				myAddress.Save(myPacket);

				retval.add(myAddress);
			}
		}

		return retval;
	}

	public PacketNode[] GetPackets() {
		PacketNode[] retval = null;

		synchronized (this) {
			retval = new PacketNode[packetList.size()];

			int count = 0;

			PacketNode currentNode = null;

			Iterator<PacketNode> iterator = packetList.iterator();

			while (iterator.hasNext()) {

				currentNode = (PacketNode) iterator.next();

				if (currentNode != null) {
					retval[count] = currentNode;
				}
				count++;
			}

			Arrays.sort(retval);

		}

		return (retval);
	}

	// adds the packet information to the address node for the UI to use
	public void Save(PacketNode newNode) {

		// critical section the list modifications
		synchronized (this) {

			// add the new packet to the start of the list
			packetList.addFirst(newNode);

			// Figure out if Sent Packet Or Recieved Packet
			if (newNode.sourceAddress.equals(address)) {
				// Add it to the Sent Packet Totals
				// Increment PacketCount
				if (totalSentLifetimePackets + 1 < Long.MAX_VALUE) {
					totalSentLifetimePackets++;
				}

				// Increment Total Bytes count;
				if (totalSentLifetimeBytes + newNode.length < Long.MAX_VALUE) {
					totalSentLifetimeBytes += newNode.length;
				}

				// add the total packet/total bytes to counters here
				if (totalSentNumberOfBytes + newNode.length < Long.MAX_VALUE) {
					totalSentNumberOfBytes += newNode.length;
				}

			} else {
				// Add it to the ReceivedPacket Totals
				// Increment PacketCount
				if (totalReceivedLifetimePackets + 1 < Long.MAX_VALUE) {
					totalReceivedLifetimePackets++;
				}

				// Increment Total Bytes count;
				if (totalReceivedLifetimeBytes + newNode.length < Long.MAX_VALUE) {
					totalReceivedLifetimeBytes += newNode.length;
				}

				// add the total packet/total bytes to counters here
				if (totalReceivedNumberOfBytes + newNode.length < Long.MAX_VALUE) {
					totalReceivedNumberOfBytes += newNode.length;
				}

			}

			// if the list length is max-ed out, remove the last entry
			if (packetList.size() > 10000) {
				PacketNode lastNode = (PacketNode) packetList.removeLast();

				if (lastNode != null) {
					// Figure out if Sent Packet or Recieved Packet
					if (newNode.sourceAddress == address) {
						totalSentNumberOfBytes -= lastNode.length;
					} else {
						totalReceivedNumberOfBytes -= lastNode.length;

					}
				}

			}

		}
	}

	public String getListLabel() {

		return address + ":" + Integer.toString(port);
	}

	// returns the number of packets for this address node
	public int getPacketCount() {

		return packetList.size();

	}

}
